package controller;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import enums.Entidades;

import util.Funcs;


import model.Account;
import model.Attributes;
import model.Budget;
import model.Category;
import model.CategoryAttribute;
import model.Currency;
import model.CurrencyExchangeRate;
import model.Locations;
import model.Payee;
import model.Project;
import model.TransactionAttribute;
import model.Transactions;

public class ImportarArquivo {

	private final String ENTITY = "$ENTITY";
	private final String FIM_ENTIDADE = "$$";
	private final String PATH_FILES = "files";
	
	private String nomeEntidade="ZERO";
	private HashMap<String, String> listaDadosMap = new HashMap<String, String>();
	
	private List<Account> listAccounts = new ArrayList<Account>();
	private List<Attributes>   listAttributes   = new ArrayList<Attributes>();
	private List<CategoryAttribute> listCategoryAttributes = new ArrayList<CategoryAttribute>();
	private List<TransactionAttribute> listTransactionAttributes = new ArrayList<TransactionAttribute>();
	private List<Budget> listBudgets = new ArrayList<Budget>();
	private List<Category> listCategories = new ArrayList<Category>();
	private List<Currency> listCurrencies = new ArrayList<Currency>();
	private List<Locations> listLocations = new ArrayList<Locations>();
	private List<Project> listProjects = new ArrayList<Project>();
	private List<Payee> listPayees = new ArrayList<Payee>();
	private List<Transactions> listTransactions = new ArrayList<Transactions>();
	private List<CurrencyExchangeRate> listCurrencyExchangeRates = new ArrayList<CurrencyExchangeRate>();
	
	public void lerArquivo(String nomeArquivo) throws Exception{
		
		try { 
			BufferedReader in = new BufferedReader(new FileReader(PATH_FILES+"/"+nomeArquivo));
			String str;
			while (in.ready()) {
				str = new String(in.readLine().getBytes(), "UTF-8");
				classificarEntidade(str);
			}
			in.close();
		} catch (IOException e) {
		
		}
		
		PercistirDados percistirDados = new PercistirDados();
		System.out.print("Currency            : "+listCurrencies.size()+" encontardos, ");
		System.out.println(percistirDados.persistirCurrency(listCurrencies)+" inseridos");
		listCurrencies = null;
		System.out.print("Attributes          : "+listAttributes.size()+" encontrados, ");
		System.out.println(percistirDados.persistirAttributes(listAttributes)+" inseridos");
		listAttributes = null;
		System.out.print("Locations           : "+listLocations.size()+" encontrados, ");
		System.out.println(percistirDados.persistirLocations(listLocations)+" inseridos");
		listLocations = null;
		System.out.print("Projects            : "+listProjects.size()+" encontardos, ");
		System.out.println(percistirDados.persistirProject(listProjects)+" inseridos");
		listProjects = null;
		System.out.print("Category            : "+listCategories.size()+" encontardos, ");
		System.out.println(percistirDados.persistirCategory(listCategories)+" inseridos");
		listCategories = null;
		System.out.print("Accounts            : "+listAccounts.size()+" encontrados, ");
		System.out.println(percistirDados.persistirAccount(listAccounts)+" inseridos");
		listAccounts = null;
		System.out.print("Payees              : "+listPayees.size()+" encontrados, ");
		System.out.println(percistirDados.persistirPayee(listPayees)+" inseridos");
		listPayees = null;
		System.out.print("CategoryAttributes  : "+listCategoryAttributes.size()+" encontados, ");
		System.out.println(percistirDados.persistirCategoryAttribute(listCategoryAttributes)+" inseridos");
		listCategoryAttributes = null;
		System.out.print("Transactions        : "+listTransactions.size()+" encontrados, ");
		System.out.println(percistirDados.persistirTransactions(listTransactions)+" inseridos");
		listTransactions = null;
		System.out.println("TransactionAttribute: "+listTransactionAttributes.size()+" encontrados, ");
		System.out.println(percistirDados.persistirTransactionAttribute(listTransactionAttributes)+" inseridos");
		listTransactionAttributes = null;
	}
	
	
	private void classificarEntidade(String linha){
		String campo;
		String dado;
		String campoEdado[] = linha.split(":");
		//System.out.println(campoEdado.length);
	
		if (campoEdado.length == 2){
			campo = campoEdado[0];
			dado =  campoEdado[1];
		}else if (campoEdado.length > 2){
			campo = campoEdado[0];
			dado =  tratarDado(campoEdado);
		}else {
			campo = linha;
			if(!campo.equals(FIM_ENTIDADE)){
				dado = "";
			}else{
				dado = null;
			}
		}
		
		if(campo.contains(ENTITY)){
			nomeEntidade = dado;
			listaDadosMap.clear();
		}
		
		if(nomeEntidade.equals(Entidades.Account.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirAccount();
			}
		}else if(nomeEntidade.equals(Entidades.Attributes.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else {
				inserirAtributes();
			}
		}else if(nomeEntidade.equals(Entidades.CategoryAttribute.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirCategoryAttribute();
			}
		}else if(nomeEntidade.equals(Entidades.TransactionAttribute.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirTransactionsAttribute();
			}
		}else if(nomeEntidade.equals(Entidades.Budget.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirBudget();
			}
		}else if(nomeEntidade.equals(Entidades.Category.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirCategory();
			}
		}else if(nomeEntidade.equals(Entidades.Currency.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirCurrency();
			}
		}else if(nomeEntidade.equals(Entidades.Locations.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirLocations();
			}
		}else if(nomeEntidade.equals(Entidades.Project.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirProject();
			}
		}else if(nomeEntidade.equals(Entidades.Payee.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirPayee();
			}
		}else if(nomeEntidade.equals(Entidades.Transactions.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirTransactions();
			}
		}else if(nomeEntidade.equals(Entidades.CurrencyExchangeRate.getNomeEntidade())){
			if(dado!=null){
				listaDadosMap.put(campo,dado);
			}else{
				inserirCurrencyExchangeRate();
			}
		}
	}
	
	private String tratarDado(String campoEdado[]){
		String retorno="";
		for (int i = 0; i < campoEdado.length; i++) {
			if(i!=0){
				retorno = retorno+campoEdado[i]+":";
			}
		}
		return retorno.substring(0, retorno.length()-1);
	}
	
	private void inserirAccount(){
		Account account =  new Account();
		account.setId(Integer.parseInt(listaDadosMap.get("_id")));
		account.setTitle(listaDadosMap.get("title"));
		account.setCreationDate(Long.parseLong(listaDadosMap.get("creation_date")));
		account.setCurrencyId(Integer.parseInt(listaDadosMap.get("currency_id")));
		account.setTotalAmount(Integer.parseInt(listaDadosMap.get("total_amount")));
		account.setType(listaDadosMap.get("type"));
		account.setIssuer(listaDadosMap.get("issuer"));
		account.setNumber(listaDadosMap.get("number"));
		account.setSortOrder(Integer.parseInt(listaDadosMap.get("sort_order")));
		//account.setIsActive(listaDadosMap.get("is_active").equals("1") ? true : false);
		account.setIsActive(Byte.parseByte(listaDadosMap.get("is_active")));
		account.setIsIncludeIntoTotals(Byte.parseByte(listaDadosMap.get("is_include_into_totals")));
		//account.setIsIncludeIntoTotals(listaDadosMap.get("is_include_into_totals").equals("1") ? true : false);
		account.setLastCategoryId(Integer.parseInt(listaDadosMap.get("last_category_id")));
		account.setLastAccountId(Integer.parseInt(listaDadosMap.get("last_account_id")));
		account.setTotalLimit(Integer.parseInt(listaDadosMap.get("total_limit")));
		account.setCardIssuer(listaDadosMap.get("card_issuer"));
		account.setClosingDay(Byte.parseByte(listaDadosMap.get("closing_day")));
		account.setPaymentDay(Byte.parseByte(listaDadosMap.get("payment_day")));
		account.setLastTransactionDate(Long.parseLong(listaDadosMap.get("last_transaction_date")));
		account.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listAccounts.add(account);
	}
	
	private void inserirAtributes(){
		Attributes attributes = new Attributes();
		attributes.setId(Integer.parseInt(listaDadosMap.get("_id")));
		attributes.setType(Integer.parseInt(listaDadosMap.get("type")));
		attributes.setName(listaDadosMap.get("name"));
		attributes.setListValues(listaDadosMap.get("list_values"));
		attributes.setDefaultValue(listaDadosMap.get("default_value"));
		attributes.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listAttributes.add(attributes);
	}
	
	private void inserirCategoryAttribute(){
		CategoryAttribute categoryAttribute = new CategoryAttribute();
		categoryAttribute.setAttributeId(Integer.parseInt(listaDadosMap.get("attribute_id")));
		categoryAttribute.setCategoryId(Integer.parseInt(listaDadosMap.get("category_id")));
		listCategoryAttributes.add(categoryAttribute);
	}
	
	private void inserirTransactionsAttribute(){
		TransactionAttribute transactionAttribute = new TransactionAttribute();
		transactionAttribute.setAttributeId(Integer.parseInt(listaDadosMap.get("transaction_id")));
		transactionAttribute.setTransactionId(Integer.parseInt(listaDadosMap.get("attribute_id")));
		transactionAttribute.setValue(listaDadosMap.get("value"));
		listTransactionAttributes.add(transactionAttribute);
	}
	
	private void inserirBudget(){
		Budget budget = new Budget();
		listBudgets.add(budget);
	}
	
	private void inserirCategory(){
		Category category = new Category();
		category.setId(Integer.parseInt(listaDadosMap.get("_id")));
		category.setTitle(listaDadosMap.get("title"));
		category.setLeft(Integer.parseInt(listaDadosMap.get("left")));
		category.setRight(Integer.parseInt(listaDadosMap.get("right")));
		category.setLastLocationId(Integer.parseInt(listaDadosMap.get("last_location_id")));
		category.setLastProjectId(Integer.parseInt(listaDadosMap.get("last_project_id")));
		category.setSortOrder(Integer.parseInt(listaDadosMap.get("sort_order")));
		category.setType(listaDadosMap.get("type"));
		category.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listCategories.add(category);
		
	}
	
	private void inserirCurrency(){
		Currency currency = new Currency();
		currency.setId(Integer.parseInt(listaDadosMap.get("_id")));
		currency.setName(listaDadosMap.get("name"));
		currency.setTitle(listaDadosMap.get("title"));
		currency.setSymbol(listaDadosMap.get("symbol"));
		currency.setIsDefault(Byte.parseByte(listaDadosMap.get("is_default")));
		currency.setDecimals(Byte.parseByte(listaDadosMap.get("decimals")));
		currency.setDecimalSeparator(Funcs.caractere(listaDadosMap.get("decimal_separator"), 1));
		currency.setGroupSeparator(Funcs.caractere(listaDadosMap.get("group_separator"), 1));
		currency.setSymbolFormat(listaDadosMap.get("symbol_format"));
		currency.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listCurrencies.add(currency);
	}
	
	private void inserirLocations(){
		Locations locations = new Locations();
		locations.setId(Integer.parseInt(listaDadosMap.get("_id")));
		locations.setName(listaDadosMap.get("name"));
		locations.setDatetime(Long.parseLong(listaDadosMap.get("datetime")));
		locations.setProvider(listaDadosMap.get("provider"));
		locations.setAccuracy(listaDadosMap.get("accuracy"));
		locations.setLatitude(Integer.parseInt(listaDadosMap.get("latitude")));
		locations.setLongitude(Integer.parseInt(listaDadosMap.get("longitude")));
		locations.setIsPayee(Byte.parseByte(listaDadosMap.get("is_payee")));
		locations.setResolvedAddress(listaDadosMap.get("resolved_address"));
		locations.setCount(Integer.parseInt(listaDadosMap.get("count")));
		locations.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listLocations.add(locations);
	}
	
	private void inserirProject(){
		Project project = new Project();
		project.setId(Integer.parseInt(listaDadosMap.get("_id")));
		project.setTitle(listaDadosMap.get("title"));
		project.setIsActive(Byte.parseByte(listaDadosMap.get("is_active")));
		project.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listProjects.add(project);
	}
	
	private void inserirPayee(){
		//System.out.println("Tamanho da lista: "+(listaDadosMap.size()));
		//if (listaDadosMap.size()==11){
			//System.out.println(listaDadosMap.get("_id"));
			//System.out.println(listaDadosMap.get("transaction_id"));
		//}
		Payee payee = new Payee();
		payee.setId(Integer.parseInt(listaDadosMap.get("_id")));
		payee.setTitle(listaDadosMap.get("title"));
		payee.setLastCategoryId(Integer.parseInt(listaDadosMap.get("last_category_id")));
		payee.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listPayees.add(payee);
	}
	
	private void inserirTransactions(){
		Transactions transactions = new Transactions();
		transactions.setId(Integer.parseInt(listaDadosMap.get("_id")));
		transactions.setFromAccountId(Funcs.inteiro(listaDadosMap.get("from_account_id")));
		transactions.setToAccountId(Funcs.inteiro(listaDadosMap.get("to_account_id")));
		transactions.setCategoryId(Funcs.inteiro(listaDadosMap.get("category_id")));
		transactions.setProjectId(Funcs.inteiro(listaDadosMap.get("project_id")));
		transactions.setLocationId(Funcs.inteiro(listaDadosMap.get("location_id")));
		transactions.setNote(listaDadosMap.get("note"));
		transactions.setFromAmount(Funcs.inteiro(listaDadosMap.get("from_amount")));
		transactions.setToAmount(Funcs.inteiro(listaDadosMap.get("to_amount")));
		transactions.setDatetime(Funcs.inteiroLong(listaDadosMap.get("datetime")));
		transactions.setProvider(listaDadosMap.get("provider"));
		transactions.setStatus(listaDadosMap.get("status"));
		transactions.setAccuracy(Funcs.decimalFloat(listaDadosMap.get("accuracy")));
		transactions.setLatitude(Funcs.inteiro(listaDadosMap.get("latitude")));
		transactions.setLongitude(Funcs.inteiro(listaDadosMap.get("longitude")));
		transactions.setIsTemplate(Funcs.strToByte(listaDadosMap.get("is_template")));
		transactions.setTemplateName(listaDadosMap.get("template_name"));
		transactions.setRecurrence(listaDadosMap.get("recurrence"));
		transactions.setStatus(listaDadosMap.get("status"));
		transactions.setIsCcardPayment(Funcs.strToByte(listaDadosMap.get("is_ccard_payment")));
		transactions.setLastRecurrence(Funcs.inteiroLong(listaDadosMap.get("last_recurrence")));
		transactions.setPayeeId(Funcs.inteiro(listaDadosMap.get("payee_id")));
		transactions.setParentId(Funcs.inteiro(listaDadosMap.get("parent_id")));
		transactions.setUpdatedOn(Funcs.inteiroLong((listaDadosMap.get("updated_on"))));
		transactions.setOriginalCurrencyId(Funcs.inteiro(listaDadosMap.get("original_currency_id")));
		transactions.setOriginalFromAmount(Funcs.inteiro(listaDadosMap.get("original_from_amount")));
		listTransactions.add(transactions);
	}
	
	private void inserirCurrencyExchangeRate(){
		CurrencyExchangeRate currencyExchangeRate = new CurrencyExchangeRate();
		currencyExchangeRate.setFromCurrencyId(Integer.parseInt(listaDadosMap.get("from_currency_id")));
		currencyExchangeRate.setToCurrencyId(Integer.parseInt(listaDadosMap.get("to_currency_id")));
		currencyExchangeRate.setRateDate(Long.parseLong(listaDadosMap.get("rate_date")));
		currencyExchangeRate.setRate(Float.parseFloat(listaDadosMap.get("rate")));
		currencyExchangeRate.setUpdatedOn(Long.parseLong(listaDadosMap.get("updated_on")));
		listCurrencyExchangeRates.add(currencyExchangeRate);
	}
}
